//! 线程池管理应用主模块
mod config_model;
mod do_task;
mod thread_pool;
mod upload_helper;

use crate::{config_model::AppConfig, thread_pool::ThreadPoolManager};
use anyhow::Result;
use common_service::ding_helper::send_msg_to_ding;
use common_service::log_helper::setup_logging;
use log::{debug, error, info, warn};
use remote_service::GWebRemoteService;
use std::env;
use std::path::PathBuf;
use std::sync::Arc;
use std::sync::atomic::Ordering;
use std::time::Duration;
use tokio::signal;

fn get_config_path() -> PathBuf {
    // 获取当前正在运行的可执行文件的完整路径
    // 例如: "/usr/local/bin/myapp" 或 "C:\Program Files\MyApp\myapp.exe"
    let mut path = env::current_exe().unwrap();

    // 移除路径的最后一部分（即可执行文件名）
    // 这样我们就跳转到了可执行文件所在的目录
    // 例如: "/usr/local/bin/" 或 "C:\Program Files\MyApp\"
    path.pop();

    // 在当前目录下添加配置文件名
    // 最终路径变为可执行文件同级目录下的 application.yml 文件
    // 例如: "/usr/local/bin/application.yml" 或 "C:\Program Files\MyApp\application.yml"
    path.push("application.yml");

    // 返回构建好的配置文件完整路径
    path
}
async fn run() -> Result<()> {
    info!("创建进程生命周期的日志守卫。。。");
    //设置日志守护者，使它的生命周期覆盖整个主函数
    let _log_guard = setup_logging();

    let config_path = get_config_path();
    info!("获取配置文件路径{:?}", config_path);
    // 使用 match 语句
    let app_config = AppConfig::from_file(config_path.to_str().unwrap()).unwrap_or_else(|e| {
        warn!("配置文件读取失败: {:?}, 使用默认配置", e);
        let config = AppConfig::default_config();
        config
    });
    debug!("配置信息: {:?}", app_config);

    let app_config = Arc::new(app_config);
    info!("创建远程服务对象");
    let remote_service = Arc::new(GWebRemoteService::new().map_err(|e| {
        error!("创建远程服务失败: {:?}", e);
        anyhow::anyhow!("创建远程服务失败: {}", e)
    })?);
    let sites = remote_service.list_sites().await.map_err(|e| {
        error!("调用远程服务获取站点列表失败: {:?}", e);
        anyhow::anyhow!("获取站点列表失败: {}", e)
    })?;
    //mark 取第一个site,后续多个站点这里需要改动
    let first_site = sites.and_then(|s| s.into_iter().next()).ok_or_else(|| {
        error!("远程服务返回空站点列表或无站点");
        anyhow::anyhow!("未找到任何站点")
    })?;
    info!("站点信息对象site_info={:?}", first_site);
    let site_info = Arc::new(first_site);

    // 创建线程池管理器
    let thread_pool = ThreadPoolManager::new(
        app_config.clone(),
        remote_service.clone(),
        site_info.clone(),
    );

    // 启动线程池
    let pool_handle = tokio::spawn({
        let thread_pool = thread_pool.clone();
        async move {
            if let Err(e) = thread_pool.start().await {
                error!("线程池启动失败: {e}");
            }
        }
    });

    //异步监控线程池状态,每5秒汇报线程池中线程数量
    let monitor_handle = tokio::spawn({
        let thread_pool = thread_pool.clone();
        async move {
            loop {
                let active_count = thread_pool.active_count.load(Ordering::SeqCst);
                info!("当前活动的线程数量: {active_count}");
                tokio::time::sleep(Duration::from_secs(5)).await;
            }
        }
    });
    // 阻塞等待终止任务信号
    info!("Ctr+C结束任务...");
    signal::ctrl_c().await?;
    info!("取消异步任务");
    pool_handle.abort();
    monitor_handle.abort();

    info!("应用进程关闭完成");
    Ok(())
}

#[tokio::main]
async fn main() {
    if let Err(e) = run().await {
        // 在这里统一拦截
        error!("程序崩溃: {:?}", e);

        // 额外逻辑：发短信、写文件、上报监控系统等
        let _ = send_msg_to_ding(&"video_slice程序崩溃，请检查日志文件").await;

        // 友好退出
        std::process::exit(1);
    };
}
